﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GameUtils.GameManager;

namespace ThouShaltNotBrick.Logic.GameStates
{
    public static class GameStateManager
    {
        #region Properties
        public static IGameState CurrState
        {
            get
            {
                if (mGameStates.Count > 0)
                {
                    return mGameStates.Peek();
                }
                else
                {
                    return null;
                }
            }
        }

        private static Stack<IGameState> mGameStates;

        private static IntroGameState mIntroGameState;
        private static MainMenuGameState mMainMenuGameState;
        private static SelectCampaignGameState mSelectCampaignGameState;
        private static PlayStartGameState mPlayStartGameState;
        private static PlayNormalGameState mPlayNormalGameState;
        private static PlayPausedGameState mPlayPausedGameState;
        private static PlayWinGameState mPlayWinGameState;
        private static PlayLossGameState mPlayLossGameState;
        private static LossGameState mLossGameState;
        private static WinLevelGameState mWinLevelGameState;
        private static WinCampaignGameState mWinCampaignGameState;
        private static HighScoresGameState mHighScoresGameState;
        #endregion

        #region Methods
        public static void Initialize(IGameManager pGameManager)
        {
            mIntroGameState = new IntroGameState();
            mIntroGameState.Initialize(pGameManager);
            mMainMenuGameState = new MainMenuGameState();
            mMainMenuGameState.Initialize(pGameManager);
            mSelectCampaignGameState = new SelectCampaignGameState();
            mSelectCampaignGameState.Initialize(pGameManager);
            mPlayStartGameState = new PlayStartGameState();
            mPlayStartGameState.Initialize(pGameManager);
            mPlayNormalGameState = new PlayNormalGameState();
            mPlayNormalGameState.Initialize(pGameManager);
            mPlayPausedGameState = new PlayPausedGameState();
            mPlayPausedGameState.Initialize(pGameManager);
            mPlayWinGameState = new PlayWinGameState();
            mPlayWinGameState.Initialize(pGameManager);
            mPlayLossGameState = new PlayLossGameState();
            mPlayLossGameState.Initialize(pGameManager);
            mLossGameState = new LossGameState();
            mLossGameState.Initialize(pGameManager);
            mWinLevelGameState = new WinLevelGameState();
            mWinLevelGameState.Initialize(pGameManager);
            mWinCampaignGameState = new WinCampaignGameState();
            mWinCampaignGameState.Initialize(pGameManager);
            mHighScoresGameState = new HighScoresGameState();
            mHighScoresGameState.Initialize(pGameManager);

            mGameStates = new Stack<IGameState>();
            ChangeState(GameStateType.Intro);
        }

        public static void Destroy()
        {
            mIntroGameState.Destroy();
            mMainMenuGameState.Destroy();
            mSelectCampaignGameState.Destroy();
            mPlayStartGameState.Destroy();
            mPlayNormalGameState.Destroy();
            mPlayPausedGameState.Destroy();
            mPlayWinGameState.Destroy();
            mPlayLossGameState.Destroy();
            mLossGameState.Destroy();
            mWinLevelGameState.Destroy();
            mWinCampaignGameState.Destroy();
            mHighScoresGameState.Destroy();
        }

        internal static void ChangeState(GameStateType pGameStateType)
        {
            ChangeState(pGameStateType, null);
        }

        internal static void ChangeState(GameStateType pGameStateType, GameStateChangeData pChangeData)
        {
            IGameState gameState = GameStateManager.GetState(pGameStateType);
            if (mGameStates.Count > 0)
            {
                IGameState prevGameState = mGameStates.Pop();
                prevGameState.Stop();
            }

            mGameStates.Push(gameState);
            gameState.Start(pChangeData);
        }

        internal static void PushState(GameStateType pGameStateType)
        {
            PushState(pGameStateType, null);
        }

        internal static void PushState(GameStateType pGameStateType, GameStateChangeData pChangeData)
        {
            IGameState gameState = GameStateManager.GetState(pGameStateType);
            if (mGameStates.Count > 0)
            {
                IGameState prevGameState = mGameStates.Peek();
                prevGameState.Pause();
            }

            mGameStates.Push(gameState);
            gameState.Start(pChangeData);
        }

        internal static void PopState()
        {
            PopState(null);
        }

        internal static void PopState(GameStateChangeData pChangeData)
        {
            if (mGameStates.Count > 0)
            {
                IGameState prevGameState = mGameStates.Pop();
                prevGameState.Stop();
            }

            if (mGameStates.Count > 0)
            {
                IGameState prevGameState = mGameStates.Peek();
                prevGameState.Resume(pChangeData);
            }
        }

        private static IGameState GetState(GameStateType pGameStateType)
        {
            switch (pGameStateType)
            {
                case GameStateType.Intro:
                    return mIntroGameState;

                case GameStateType.MainMenu:
                    return mMainMenuGameState;

                case GameStateType.SelectCampaign:
                    return mSelectCampaignGameState;

                case GameStateType.PlayStart:
                    return mPlayStartGameState;

                case GameStateType.PlayNormal:
                    return mPlayNormalGameState;

                case GameStateType.PlayPaused:
                    return mPlayPausedGameState;

                case GameStateType.PlayWin:
                    return mPlayWinGameState;

                case GameStateType.PlayLoss:
                    return mPlayLossGameState;

                case GameStateType.Loss:
                    return mLossGameState;

                case GameStateType.WinLevel:
                    return mWinLevelGameState;

                case GameStateType.WinCampaign:
                    return mWinCampaignGameState;

                case GameStateType.HighScores:
                    return mHighScoresGameState;

                default:
                    {
                        string errorMessage = string.Format("Invalid game state type: '{0}'.", pGameStateType);
                        throw new ArgumentException(errorMessage, "pGameStateType");
                    }
            }
        }
        #endregion
    }
}